package com.liu.security.utils;

import com.liu.security.pojo.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;


/**
 * JWT工具类
 */
public class JwtUtil {

    // 可以使用更复杂的密钥，也可以从配置文件中读取
    private final static SecretKey secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256); // 使用 HS256 算法

    // Token 有效期（如 5 小时）
    private final static long JWT_TOKEN_VALIDITY = 5 * 60 * 60 * 1000;  //5小时

    // 从 token 中获取用户名
    public static String getUsernameFromToken(String token) {
        return getClaimFromToken(token, Claims::getSubject);
    }

    public static User getUserFromToken(String token) {
        final Claims claims = getAllClaimsFromToken(token);
        User user = new User();
        user.setUsername(claims.getSubject());
        user.setId(Long.valueOf(claims.getId()));
        return user;
    }

    // 从 token 中获取到期时间
    public static Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token, Claims::getExpiration);
    }

    // 从 token 中获取指定的 claims
    public static <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = getAllClaimsFromToken(token);
        return claimsResolver.apply(claims);
    }

    // 获取所有的 claims
    private static Claims getAllClaimsFromToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    // 验证 token 是否过期
    private static Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }

    // 生成 token
    public static String generateToken(User user) {
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, user);
    }

    // 生成 token（可以加入自定义的 claims）
    private static String doGenerateToken(Map<String, Object> claims, User user) {
        return Jwts.builder()
                .setId(user.getId().toString())
                .setClaims(claims)
                .setSubject(user.getUsername())
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY))
                .signWith(secretKey, SignatureAlgorithm.HS256)
                .compact();
    }

    // 验证 token
    public static Boolean validateToken(String token, String username) {
        final String tokenUsername = getUsernameFromToken(token);
        return (tokenUsername.equals(username) && !isTokenExpired(token));
    }
}